package de.projectgoodmorning.alarm.activities;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;

import android.app.Activity;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import de.projectgoodmorning.alarm.R;
import de.projectgoodmorning.alarm.activities.util.Actionbar;
import de.projectgoodmorning.alarm.dialogs.CommandDialog;
import de.projectgoodmorning.alarm.dialogs.CommandListener;
import de.projectgoodmorning.alarm.dialogs.ConfirmDialog;
import de.projectgoodmorning.alarm.model.gateway.CombinedAlarm;
import de.projectgoodmorning.alarm.model.gateway.GatewayAlarm;
import de.projectgoodmorning.alarm.model.gateway.RingAlarm;
import de.projectgoodmorning.alarm.storage.AlarmStorage;
import de.projectgoodmorning.alarm.util.RsrcHelper;

/**
 * Die ManageAlarmActivity Klasse ist fuer die konkrete Bearbeitung eines Alarms
 * als auch fuer die Erstellung eines neuen Alarms zustaendig.
 * 
 * Name, Uhrzeit als auch beliebig viele Vor- und Nachaktivitaeten koennen hier
 * erstellt und dem Alarm zugewiesen werden.
 */
public class ManageAlarmActivity extends Activity implements OnClickListener {
	private static final String TAG = ManageAlarmActivity.class.getName();

	private static final int TIME_DIALOG_ID = 0;
	private static final int ADD_COMMAND_DIALOG_ID = 1;
	private static final int EDIT_COMMAND_DIALOG_ID = 2;
	
	private boolean isNewAlarm;
	
	private EditText nameEditText;
	private Button chooseTimeButton, addCommandButton, okButton, cancelButton;
	private ListView list;

	private CommandDialog addCommandDialog;
	private CommandDialog editCommandDialog;
	private OnTimeSetListener beginTimePickerListener;
	
	private CombinedAlarm backup;
	private CombinedAlarm managedCombinedAlarm;
	private AlarmStorage storage;
	
	private GatewayAlarm[] alarms;
	
	@Override
	public void onCreate( Bundle savedInstanceState ) {
		super.onCreate( savedInstanceState );
		setContentView( R.layout.activity_manage_alarm );

		nameEditText = ( EditText ) findViewById( R.id.nameEditText );
		chooseTimeButton = ( Button ) findViewById( R.id.chooseTimeButton );
		addCommandButton = ( Button ) findViewById( R.id.addCommandButton );
		list = ( ListView ) findViewById( R.id.commandList );
		okButton = ( Button ) findViewById( R.id.okButton );
		cancelButton = ( Button ) findViewById( R.id.cancelButton );

		okButton.setOnClickListener( this );
		cancelButton.setOnClickListener( this );
		chooseTimeButton.setOnClickListener( this );
		addCommandButton.setOnClickListener( this );

		Actionbar action = new Actionbar( this );
		action.setOnBackButtonClicked( new View.OnClickListener() {
			@Override
			public void onClick( View v ) {
				onBackPressed();
			}
		} );
		
		list.setOnCreateContextMenuListener( this );
		
		addCommandDialog = new CommandDialog( this, new CommandListener() {
			@Override
			public void command( GatewayAlarm alarm ) {
				managedCombinedAlarm.addAlarm( alarm.seconds, alarm.color );
				createList( managedCombinedAlarm );
			}
		} );
		
		editCommandDialog = new CommandDialog( this, new CommandListener() {
			@Override
			public void command( GatewayAlarm alarm ) {
				createList( managedCombinedAlarm );
			}
		} );

		storage = new AlarmStorage( this );
		
		Bundle extras = getIntent().getExtras();
		if( extras.containsKey( MainActivity.NEW_ALARM ) ) {
			isNewAlarm = true;

			Calendar cal = Calendar.getInstance();
			cal.set( Calendar.HOUR_OF_DAY, 7 );
			cal.set( Calendar.MINUTE, 0 );
			cal.set( Calendar.SECOND, 0 );
			
			RingAlarm ringAlarm = new RingAlarm( cal );
			managedCombinedAlarm = new CombinedAlarm( ringAlarm );
			fillComponents( managedCombinedAlarm );
			
		} else 	if( extras.containsKey( MainActivity.MANAGED_ALARM_ID ) ) {
			managedCombinedAlarm = storage.getById( extras.getInt( MainActivity.MANAGED_ALARM_ID ) );
			backup = copy( managedCombinedAlarm );
			
			if( managedCombinedAlarm == null ) {
				showToast( RsrcHelper.getString( R.string.msg_alarmNotFound, this ) );
				finish();
			} else {
				fillComponents( managedCombinedAlarm );
			}
		}
		
		beginTimePickerListener = new OnTimeSetListener() {
			public void onTimeSet( TimePicker view, int hourOfDay, int minuteOfHour ) {
				SimpleDateFormat sdf = new SimpleDateFormat( "HH:mm" );
				
				Calendar cal = Calendar.getInstance();
				cal.set( cal.get( Calendar.YEAR ), cal.get( Calendar.MONTH ), 
						cal.get( Calendar.DAY_OF_MONTH ), hourOfDay, minuteOfHour, 0 );
				
				managedCombinedAlarm.getMainAlarm().setMoment( cal );
				String clock = RsrcHelper.getString( R.string.clock, getApplicationContext() );
				chooseTimeButton.setText( sdf.format( cal.getTime() ) + " " + clock );
			}
		};
	}
	
	@Override
	public boolean onContextItemSelected( MenuItem item ) {
		AdapterView.AdapterContextMenuInfo info = 
				( AdapterView.AdapterContextMenuInfo ) item.getMenuInfo();

		String selected = item.getTitle().toString();
		final GatewayAlarm ga = alarms[info.position];
		
		// DELETE
		if( selected.equals( RsrcHelper.getString( R.string.delete, this ) ) ) {
			ConfirmDialog dialog = new ConfirmDialog( this );
			dialog.setOnCancelClicked( new DialogInterface.OnClickListener() {
				@Override
				public void onClick( DialogInterface dialog, int which ) {
					dialog.cancel();
				}
			} );
			
			dialog.setOnConfirmClicked( new DialogInterface.OnClickListener() {
				@Override
				public void onClick( DialogInterface dialog, int which ) {
					managedCombinedAlarm.removeAlarm( ga );
					createList( managedCombinedAlarm );
					Log.d( TAG, "Command removed" );
				}
			} );
			
			dialog.show();
		}

		// EDIT
		if( selected.equals( RsrcHelper.getString( R.string.edit, this ) ) ) {
			editCommandDialog.setAlarm( ga );
			showDialog( EDIT_COMMAND_DIALOG_ID );
		}
		
		return super.onContextItemSelected( item );
	}
	
	@Override
	public void onCreateContextMenu( ContextMenu menu, View v, ContextMenuInfo menuInfo ) {
		super.onCreateContextMenu( menu, v, menuInfo );
		menu.add( Menu.NONE, 0, 0, RsrcHelper.getString( R.string.delete, this ) );
		menu.add( Menu.NONE, 0, 0, RsrcHelper.getString( R.string.edit, this ) );
	}
	
	@Override
	protected Dialog onCreateDialog( int id ) {
		switch( id ) {
		case TIME_DIALOG_ID:
			Calendar cal = Calendar.getInstance();
			cal.setTimeInMillis( managedCombinedAlarm.getMainAlarm().getMoment() );
			
			int minute = cal.get( Calendar.MINUTE );
			int hour = cal.get( Calendar.HOUR_OF_DAY );
			
			return new TimePickerDialog( this, 
					beginTimePickerListener, hour, minute, true );
		
		case ADD_COMMAND_DIALOG_ID:
			return addCommandDialog;

		case EDIT_COMMAND_DIALOG_ID:
			return editCommandDialog;
		}
		return null;
	}
	
	@Override
	public void onClick( View v ) {
		if( v == chooseTimeButton ) {
			showDialog( TIME_DIALOG_ID );
		}
		
		if( v == addCommandButton ) {
			showDialog( ADD_COMMAND_DIALOG_ID );
		}

		if( v == okButton && isValidForSave() ) {
			if( !isNewAlarm ) {
				storage.removeById( managedCombinedAlarm.id );
			}
			
			managedCombinedAlarm.name = nameEditText.getText() + "";
			storage.add( managedCombinedAlarm );

			Intent i = new Intent();
			setResult( RESULT_OK, i );
			finish();
		}

		if( v == cancelButton ) {
			if( !isNewAlarm ) {
				storage.removeById( managedCombinedAlarm.id );
				storage.add( backup );
			}
			
			setResult( RESULT_CANCELED, new Intent() );
			finish();
		}
	}
	
	/////////// Helpers /////////////////////////////////////
	private void fillComponents( CombinedAlarm alarm ) {
		if( alarm != null ) {
			nameEditText.setText( alarm.name );
			
			if( nameEditText.getText().length() != 0 ) {
				cancelButton.setFocusableInTouchMode( true );
				cancelButton.requestFocus();
			}
			
			SimpleDateFormat sdf = new SimpleDateFormat( "HH:mm" );
			
			String clock = RsrcHelper.getString( R.string.clock, getApplicationContext() );
			chooseTimeButton.setText( sdf.format( alarm.getMainAlarm().getMoment() ) + " " + clock );
			
			createList( alarm );
		}
	}

	private void createList( CombinedAlarm alarm ) {
		alarms = alarm.getGatewayAlarms();
		Arrays.sort( alarms, new Comparator<GatewayAlarm>() {
			@Override
			public int compare( GatewayAlarm lhs, GatewayAlarm rhs ) {
				if( lhs.seconds < rhs.seconds )
		            return -1;
		        if( lhs.seconds > rhs.seconds )
		            return 1;
		            
		        return 0;
			}
		} );
		
		list.setAdapter( new ArrayAdapter<GatewayAlarm>( 
				this, R.layout.command_list_item, alarms ) {
			
			@Override
			public View getView( int position, View convertView, 
					android.view.ViewGroup parent ) {
				
				LayoutInflater inflater = ManageAlarmActivity.this.getLayoutInflater();
				View row = inflater.inflate( R.layout.command_list_item, parent, false );
		
				GatewayAlarm alarm = alarms[position];
				
				View v = row.findViewById( R.id.colorPreview );
				TextView info = ( TextView ) row.findViewById( R.id.commandoText );

				v.setBackgroundColor( alarm.color );
				
				boolean isBefore = alarm.seconds < 0 ? true : false;
				
				RsrcHelper res = new RsrcHelper( getApplicationContext() );
				String typeStr = "";
				if( isBefore ) {
					typeStr = res.getString( R.string.before );
				} else {
					typeStr = res.getString( R.string.after );
				}
				
				String secs = res.getString( R.string.seconds );
				
				if( alarm.seconds == 0 ) {
					info.setText( res.getString( R.string.toWakeUp ) );
				} else {
					info.setText( Math.abs( alarm.seconds ) + " " + secs+ " " + typeStr );
				}
				
				return row;
			};
		} );
		
		list.setOnCreateContextMenuListener( this );
	}
	
	private boolean isValidForSave() {
		if( nameEditText.getText().length() == 0 ) {
			showToast( RsrcHelper.getString( R.string.msg_insertName, this ) );
			return false;
		}
		
		return true;
	}
	
	private void showToast( String message ) {
		Toast.makeText( this, message, Toast.LENGTH_LONG ).show();
	}
	
	private CombinedAlarm copy( CombinedAlarm alarm ) {
		
		RingAlarm ring = new RingAlarm( alarm.getMainAlarm().getMoment() );
		CombinedAlarm ca = new CombinedAlarm( ring );
		
		ca.id = alarm.id;
		ca.name = alarm.name;
		
		for( GatewayAlarm ga : alarm.getGatewayAlarms() ) {
			ca.addAlarm( ga.seconds, ga.color );
		}
		
		return ca;
	}
	/////////////////////////////////////////////////////////
}
